Skip to content

Ncto 141 add image upload on project settings#19

Merged
Louis-rollet merged 3 commits intomainfrom
NCTO-141-add-image-upload-on-project-settings
Mar 29, 2026
Merged

Ncto 141 add image upload on project settings#19
Louis-rollet merged 3 commits intomainfrom
NCTO-141-add-image-upload-on-project-settings

Conversation

@Louis-rollet
Copy link
Copy Markdown
Collaborator

Jira ticket

https://naucto.atlassian.net/browse/NCTO-141

What does your MR do ?

Linked to frontend PR, this will add the way to upload images on the S3 then will be able to laod then using the cdn urls, currently it's implemented on ongoing projects and published projects.
The backend adds the apis to be able to upload and get the images of user profiles or projects

How to test it

Open a project and in the project settings you can now upload an image for this project

Screenshot

Notes

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds backend support for uploading project/user images to S3 and retrieving their CDN URLs, including new unauthenticated (“public”) endpoints intended for published projects and user profile pictures.

Changes:

  • Tightens image upload validation (max size + MIME type) for project images and user profile pictures.
  • Updates project image retrieval to return a CDN URL payload and adds new public endpoints to fetch CDN URLs for published project images and user profile pictures.
  • Extends Swagger/OpenAPI documentation to reflect new endpoints and updated response shapes.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
swagger.json Updates OpenAPI docs for image upload validation/errors, changes project image GET response, and adds new public image URL endpoints + schema.
src/swagger.app.module.ts Registers PublicController in the Swagger-only module for documentation generation.
src/routes/user/user.controller.ts Adds image MIME validation and sets uploaded profile pictures to public-read.
src/routes/public/public.module.ts Introduces a new module wiring Prisma + S3 for the public routes.
src/routes/public/public.controller.ts Adds public endpoints to fetch CDN URLs for published project images and user profile pictures.
src/routes/public/dto/image-url-response.dto.ts Adds a DTO for { url } responses.
src/routes/project/project.controller.ts Adds collaborator guard for upload/get image, validates MIME type, switches GET image response to { url }, and sets uploaded project images to public-read.
src/app.module.ts Registers PublicModule in the main app module.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +466 to +480
@ApiResponse({
status: 200,
description: "Signed cookies and CDN resource URL",
type: SignedCdnResourceDto
description: "CDN URL for the project image",
schema: {
type: "object",
properties: {
url: { type: "string", example: "https://cdn.example.com/projects/42/image" }
}
}
})
@ApiResponse({ status: 403, description: "Forbidden" })
@ApiResponse({ status: 404, description: "Image not found" })
async getProjectImage(
@Param("id", ParseIntPipe) id: number,
@Res() res: Response
): Promise<void> {
@Param("id", ParseIntPipe) id: number
): Promise<{ url: string }> {
Comment on lines +50 to +63
const project = await this.prismaService.project.findUnique({
where: { id },
select: { id: true, status: true }
});

if (!project) {
throw new NotFoundException(`Project with ID ${id} not found`);
}

if (project.status !== "COMPLETED") {
throw new NotFoundException(
`Project with ID ${id} is not published`
);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good suggestion from Copilot

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines +102 to +108
throw new NotFoundException(`User with ID ${id} not found`);
}

const key = `users/${id}/profile`;
const exists = await this.s3Service.fileExists(key);
if (!exists) {
throw new NotFoundException("Profile picture not found");
originalName: file.originalname
}
});
await this.s3Service.setObjectPublicRead(key);
swagger.json Outdated
Comment on lines +616 to +622
"type": "object",
"properties": {
"url": {
"type": "string",
"example": "https://cdn.example.com/projects/42/image"
}
}
originalName: file.originalname
}
});
await this.s3Service.setObjectPublicRead(key);
Copy link
Copy Markdown
Contributor

@alexis-belmonte alexis-belmonte left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good work!

originalName: file.originalname
}
});
await this.s3Service.setObjectPublicRead(key);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ehh we can ignore this

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not really otherwise we cannot have access to the ressource with the cdn

Comment on lines +50 to +63
const project = await this.prismaService.project.findUnique({
where: { id },
select: { id: true, status: true }
});

if (!project) {
throw new NotFoundException(`Project with ID ${id} not found`);
}

if (project.status !== "COMPLETED") {
throw new NotFoundException(
`Project with ID ${id} is not published`
);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good suggestion from Copilot

const key = `projects/${id}/image`;
const exists = await this.s3Service.fileExists(key);
if (!exists) {
throw new NotFoundException("Project image not found");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be here a NoContentException (if it exists?)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the routes should be moved to their respective controllers over creating a new controller.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put this in routes/common/dto/...

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Collaborator

@Priax Priax left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me

@Louis-rollet Louis-rollet merged commit fea65bf into main Mar 29, 2026
2 checks passed
@Louis-rollet Louis-rollet deleted the NCTO-141-add-image-upload-on-project-settings branch March 29, 2026 10:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants